package cartagows.wsframework.wsatomictransaction;

import org.apache.axiom.om.OMElement;

import cartago.ArtifactId;
import cartago.CartagoException;
import cartago.Op;
import cartago.OpFeedbackParam;
import cartago.OpRequestTimeoutException;
import cartago.util.agent.NoPerceptionException;
import cartagows.CartagowsParam;
import cartagows.WSMsgInfo;
import cartagows.util.WSAgent;
import cartagows.util.XMLib;
import cartagows.wsframework.core.FaultBuilder;
import cartagows.wsframework.wscoordination.WSCoordinationErrorParam;
import cartagows.wsframework.wscoordination.WSCoordinationMessageElem;
import cartagows.wsframework.wscoordination.WSCoordinationParam;


public class ATCoordinator extends WSAgent{

	
	private ArtifactId wsPanel;
	private ArtifactId messagesWarehouse;
	private ArtifactId activitiesRegistry; 
	
	public ATCoordinator(String agentName) throws CartagoException{
		super(agentName);
		
		wsPanel = makeArtifact(WSAtomicTransactionParam.COORDINATOR_SERVICE_WSPANEL_DEF_NAME, CartagowsParam.WSPANEL_CLASS_PATH,
				new Object[]{WSAtomicTransactionParam.WSDL_URI, WSAtomicTransactionParam.COORDINATOR_SERVICE_NAME});
		
		messagesWarehouse = lookupArtifact(WSCoordinationParam.ACTIVITIES_MSG_WAREHOUSE_DEF_NAME);
		activitiesRegistry = lookupArtifact(WSCoordinationParam.ACTIVITIES_REGISTRY_DEF_NAME);
	}

	public void run(){

		log("[ATCOORDINATOR_MAIN_SERVICE:]Starting");
		
		while(true){
			
			OMElement outputMsg = null;
			OpFeedbackParam<WSMsgInfo> res = new OpFeedbackParam<WSMsgInfo>();
			
			try {

				//Waiting for requests
				log("[ATCOORDINATOR_MAIN_SERVICE:]Waiting request");

				doAction(wsPanel, new Op("getWSMsg", res));
				WSMsgInfo inputMsg = res.get();
				
				OMElement header = XMLib.getInstance().buildElementFromString(inputMsg.getHeader());
				String activityId = XMLib.getInstance().getElementValue(WSCoordinationMessageElem.COORDINATION_CONTEXT,
						WSCoordinationMessageElem.IDENTIFIER, header);

				//activityId check
				if(activityId==null){
					log("[ATCOORDINATOR_MAIN_SERVICE:]"+WSCoordinationErrorParam.FAULT_INVALID_PARAMETER_REASON);
					outputMsg = FaultBuilder.getInstance().buildSOAPFault(
							WSCoordinationErrorParam.FAULT_INVALID_PARAMETER_CODE,
							WSCoordinationErrorParam.FAULT_INVALID_PARAMETER_SUBCODE,
							WSCoordinationErrorParam.FAULT_INVALID_PARAMETER_REASON, "");
				}
				//activityId not null
				else{
					//Check if the activityId is present in the ActivityRegistry
					OpFeedbackParam<Boolean> checkRes = new OpFeedbackParam<Boolean>();
					//Check if the activity identified by activityId is stored into the activitiesRegistry 
					doAction(activitiesRegistry, new Op("checkActivityPresence", activityId, checkRes));

					//Activity found, message dispatch through the messagesWarehouse
					if(checkRes.get()==true){
						log("[ATCOORDINATOR_MAIN_SERVICE:]Message dispatch through warehouse");
						doAction(messagesWarehouse, new Op("insertMessage", activityId ,inputMsg));
					}
					//Error: activity not found, probably has been provided a wrong activityId  
					else{
						
						log("[ATCOORDINATOR_MAIN_SERVICE:]"+WSCoordinationErrorParam.FAULT_INVALID_PARAMETER_REASON);
						outputMsg = FaultBuilder.getInstance().buildSOAPFault(
								WSCoordinationErrorParam.FAULT_INVALID_PARAMETER_CODE,
								WSCoordinationErrorParam.FAULT_INVALID_PARAMETER_SUBCODE,
								WSCoordinationErrorParam.FAULT_INVALID_PARAMETER_REASON, "");
					}
				}
				//If outputMsg!=null a fault has occurred
				if(outputMsg!=null){
					try {
						OpFeedbackParam<String> replyId = new OpFeedbackParam<String>();
						doAction(wsPanel, new Op("sendWSReply", inputMsg, outputMsg.toString(), replyId), CartagowsParam.LONG_TIMEOUT);
						log("[ATCOORDINATOR_MAIN_SERVICE:]Reply sent successfully - id: " + replyId.get());
					} catch (NoPerceptionException ex) {
						log("[ATCOORDINATOR_MAIN_SERVICE:]Reply failed.");
					}
				}
			}
			catch(OpRequestTimeoutException ex){
				log("[ATCOORDINATOR_MAIN_SERVICE:]No msg");
			}
			catch(Exception ex){
				log("[ATCOORDINATOR_MAIN_SERVICE:]"+ ex.getMessage() +" "+ ex.getCause());
			}
		}
	}
}
